<?php

namespace app\common\service\driver;

use app\common\constant\driving\CommonConstant;
use app\common\constant\driving\DriverConstant;
use app\common\constant\driving\DriverMoneyLogConstant;
use app\common\model\driving\Driver;
use app\common\model\driving\Order;
use app\common\model\driving\OrderReceive;
use app\common\model\driving\OrderServe;
use app\common\model\driving\OrderTrace;
use app\common\model\driving\Pay;
use hichefu\Api;
use think\Db;
use think\Exception;

/**
 * 订单服务类
 **/
class OrderService
{

    /**
     * 首页
     *
     * @param mixed $user 用户信息
     **/
    public static function index_driver($user)
    {
        $mk_time = mk_time(1);
        $time_data = [date('Y-m-d H:i:s', $mk_time['start']), date('Y-m-d H:i:s', $mk_time['end'])];
        $order = Pay::where('driver_id', $user['id'])
            ->where('status', CommonConstant::STATUS_PAID)
            ->where('paytime', 'between', $time_data)
            ->field('id,driver_amount')
            ->select();
        $today_order_amount = 0;
        $today_order_num = count($order);
        foreach ($order as $val) {
            $today_order_amount = bcadd($today_order_amount, $val['driver_amount'], 2);
        }
        $afoot_order_num = Order::where('driver_id', $user['id'])
            ->where('status', 'in', [Api::STAGE_11, Api::STAGE_13])
            ->count();

        $is_online = $user['is_online'];
        return compact('is_online', 'today_order_amount', 'today_order_num', 'afoot_order_num');
    }

    /**
     * 统计
     *
     * @param integer $type 类型
     * @param string $start_time 开始时间
     * @param string $end_time 结束时间
     * @param mixed $user 用户信息
     **/
    public static function statistics_driver($type, $start_time, $end_time, $user)
    {
        $type = $type > 0 ? $type : 1;
        if ($type == 4 && !empty($start_time)) {
            $time_data = [$start_time . ' 00:00:00', $end_time . ' 11:59:59'];
        } else {
            $mk_time = mk_time($type);
            $time_data = [date('Y-m-d H:i:s', $mk_time['start']), date('Y-m-d H:i:s', $mk_time['end'])];
        }
        $order = Pay::where('driver_id', $user['id'])
            ->where('status', CommonConstant::STATUS_PAID)
            ->where('paytime', 'between', $time_data)
            ->field('id,driver_amount')
            ->select();
        $today_order_amount = 0;
        $today_order_num = count($order);
        foreach ($order as $val) {
            $today_order_amount = bcadd($today_order_amount, $val['driver_amount'], 2);
        }
        return compact('today_order_amount', 'today_order_num');
    }

    /**
     * 列表
     *
     * @param string $function
     * @param mixed $user 用户信息
     * @param integer $page 页数
     * @param integer $page_size 每页数量
     * @param integer $status 订单状态
     * @return array
     */
    public static function list_driver($function, Driver $user, $page, $page_size, $status)
    {
        $page_size = $page_size > 0 ? $page_size : config('paginate.list_rows');
        if (!($page >= 1)) $page = 1;
        $offset = ($page - 1) * $page_size;

        if ($function == 'Driver.orderTaking/list') {
            $where = [];
            $where['driver_id'] = 0;
            $where['status'] = Api::STAGE_1;
            $total = Order::where($where)->count('id');
            $data = [];
            if (!$total) {
                return compact("total", "data");
            }
            $user->driver_location;
            $field = "*,(POWER(MOD(ABS(start_lng - " . $user['driver_location']['lng'] . "),360),2) + POWER(ABS(start_lat - " . $user['driver_location']['lat'] . "),2)) AS distance";
            $list = Order::with(['channel' => function ($query) {
                $query->field('name,label');
            }])
                ->where($where)
                ->field($field)
                ->order('distance asc')
                ->page($page, $page_size)
                ->select();
            $data = $list;
            return compact("total", "data");
        }
        if ($function == 'Driver.order/list') {
            $where = [];
            $where['driver_id'] = $user['id'];
            $where['status'] = ['neq', Api::STAGE_1];
            if ($status) {
                if ($status == Api::STAGE_11) {
                    $where['status'] = ['in', [Api::STAGE_11, Api::STAGE_13]];
                } else {
                    $where['status'] = $status;
                }
            }
            $total = Order::where($where)->count('id');
            $data = [];
            if (!$total) {
                return compact("total", "data");
            }
            $list = Order::with(['channel' => function ($query) {
                $query->field('name,label');
            }])
                ->where($where)
                ->order('accept_time desc')
                ->page($page, $page_size)
                ->select();
            $data = $list;
            return compact("total", "data");
        }
    }

    /**
     * 详情
     *
     * @param string $function
     * @param string|integer $order_id 订单号|订单ID
     * @param mixed $user 用户信息
     * @return mixed
     */
    public static function detail_driver($function, $order_id, $user)
    {
        if ($function == 'Driver.orderTaking/detail') {
            $order = Order::with(['channel' => function ($query) {
                $query->field('name,label');
            }])
                ->where('order_id', $order_id)
                ->find();
        }
        if ($function == 'Driver.order/detail') {
            $order = Order::with(['channel' => function ($query) {
                $query->field('name,label');
            }])
                ->where('order_id', $order_id)
                ->where('driver_id', $user['id'])
                ->find();
            if (!$order) {
                except('订单不存在');
            }
        }
        if ($function == 'Driver.order/trace') {
            $order = OrderTrace::where('oid', $order_id)
                ->field('id,waypoints,waypoints_16,json')
                ->find();
        }
        return $order;
    }

    /**
     * 接单
     *
     * @param integer $order_id 订单号
     * @param mixed $user 用户信息
     * @return bool
     **/
    public static function create_driver($order_id, $user)
    {
        if ($user['is_online'] != DriverConstant::ONLINE_1) {
            except('未开启听单，不能接单');
        }
        if ($user['oid'] > 0) {
            except('有进行中的订单，不能接单');
        }
        $index = DriverService::index($user);
        if ($user['money'] < $index['order_receive_money']) {
            except($index['order_receive_money_text']);
        }

        $order = Order::where('order_id', $order_id)->find();
        if (!$order) {
            except('订单不存在');
        }
        if ($order['status'] != Api::STAGE_1) {
            except('订单状态不是已受理');
        }

        $status = Api::STAGE_11;
        Db::startTrans();
        try {
            $is_third = ChannelService::is_third($order['channel_label']);
            if ($is_third) {
                OrderReceive::where('order_id', $order_id)->update(['status' => $status]);
            }
            $data['status'] = $status;
            $data['driver_id'] = $user['id'];
            $data['accept_time'] = date('Y-m-d H:i:s');
            $order->save($data);
            Db::commit();
        } catch (Exception $e) {
            Db::rollback();
            except($e->getMessage());
        }

        try {
            OrderReceiveService::driving($order['channel_label'], 'updateOrderStatus', $status, $order, ['driver' => $user, 'location' => []]);
        } catch (Exception $e) {
            except($e->getMessage());
        }
        return true;
    }


    /**
     * 订单操作方法
     *
     * @param integer $order_id 订单号
     * @param array $params 传值数据
     * @param mixed $user 用户信息
     * @param string $function 方法名 start end
     * @return mixed
     */
    public static function make_driver($order_id, $params, $user, $function)
    {
        $order = Order::where('order_id', $order_id)
            ->where('driver_id', $user['id'])
            ->find();
        if (!$order) {
            except('订单不存在');
        }
        $time = date('Y-m-d H:i:s');
        if ($function == 'start') {
            if ($order['status'] != Api::STAGE_11) {
                except('订单状态不是已接单');
            }
            $serve_data = [
                'start_mileage' => $params['start_mileage'],
                'start_images' => $params['start_images'],
                'start_time' => $time,
            ];
            $status = Api::STAGE_13;
            $data = [
                'status' => $status,
                'start_time' => $time,
            ];
        }
        if ($function == 'end') {
            if ($order['status'] != Api::STAGE_13) {
                except('订单状态不是已验车');
            }
            if ($order['end_code'] != $params['end_code']) {
                except('交车码错误');
            }
            $serve_data = [
                'end_mileage' => $params['end_mileage'],
                'end_car_image' => $params['end_car_image'],
                'end_dashboard_image' => $params['end_dashboard_image'],
                'end_time' => $time,
            ];
            $status = Api::STAGE_15;
            $data = [
                'status' => $status,
                'end_time' => $time,
            ];
        }

        Db::startTrans();
        try {
            $order->save($data);
            OrderServe::where('oid', $order['id'])->update($serve_data);
            if ($function == 'end') {
                $is_third = ChannelService::is_third($order['channel_label']);
                $money_type = $is_third == true ? 'freeze_money' : 'money';
                $log_data = [
                    'driver_id' => $user['id'],
                    'type' => DriverMoneyLogConstant::TYPE_1,
                    'change_type' => DriverMoneyLogConstant::CHANGE_TYPE_1,
                    'money' => $order['driver_amount'],
                    'memo' => $order_id,
                ];
                DriverService::money($log_data, $user['id'], $user, $money_type);
                $user->order_num = $user->order_num + 1;
                $user->oid = 0;
                $user->save();
            }
            Db::commit();
        } catch (Exception $e) {
            Db::rollback();
            except($e->getMessage());
        }

        try {
            OrderReceiveService::driving($order['channel_label'], 'updateOrderStatus', $status, $order);
        } catch (Exception $e) {
            except($e->getMessage());
        }
        return true;
    }

    /**
     * 订单支付
     *
     * @param string $order_id 订单号
     * @param mixed $user 用户信息
     * @return array
     */
    public static function pay_driver($order_id, $user)
    {
        $order = Order::where('order_id', $order_id)
            ->where('driver_id', $user['id'])
            ->find();
        if (!$order) {
            except('订单不存在');
        }
        if ($order['status'] != Api::STAGE_13) {
            except('订单状态不是已验车');
        }
        if (!empty($order['end_code'])) {
            except('订单已支付');
        }

        $paytype = CommonConstant::PAYTYPE_WECHAT;
        $apptype = CommonConstant::APPTYPE_SCAN;
        $response = [];
        $order_id = $order['order_id'];
        $payamount = $order['total_fee']; // 支付金额
        $is_third = ChannelService::is_third($order['channel_label']);
        if(!$is_third){
            $epay = get_addon_info('epay');
            if (empty($epay) || !$epay['state']) {
                except("请先在后台安装并配置微信支付宝整合插件");
            }
            if ($paytype == CommonConstant::PAYTYPE_WECHAT) {
                except('微信APP支付暂未开通');
            }
        }
        if (!$order['is_end']) {
            $trace_data = FreightRuleService::get_kl($order);
            $payamount = $trace_data['total_fee'];
            if ($is_third) {
                if (config('site.is_third')) {
                    try {
                        OrderReceiveService::driving($order['channel_label'], 'submitOrderBill', Api::STAGE_14, $order, ['trace' => $trace_data]);
                    } catch (Exception $e) {
                        except($e->getMessage());
                    }

                    try {
                        OrderReceiveService::driving($order['channel_label'], 'updateOrderStatus', Api::STAGE_14, $order);
                    } catch (Exception $e) {
                        except($e->getMessage());
                    }

                    try {
                        $result = OrderReceiveService::driving($order['channel_label'], 'getTotalFee', Api::STAGE_14, $order);
                    } catch (Exception $e) {
                        except($e->getMessage());
                    }
                    $payamount = $result['totalFee'];
                }

                $data['paytime'] = date('Y-m-d H:i:s');
                $data['status'] = CommonConstant::STATUS_PAID;
                $data['transaction_id'] = 'order123456';
                $order_data['end_code'] = \fast\Random::numeric(4);
                $paytype = CommonConstant::PAYTYPE_BANK;
                $apptype = '';
                $response = array_merge($response, $order_data);
            }
            $driver_amount = ChannelService::get_amount($order['channel_label'], $payamount);

            Db::startTrans();
            try {
                $data['oid'] = $order['id'];
                $data['driver_id'] = $user['id'];
                $data['order_id'] = $order_id;
                $data['amount'] = $payamount;
                $data['payamount'] = $payamount;
                $data['paytype'] = $paytype;
                $data['apptype'] = $apptype;
                $data['driver_amount'] = $driver_amount;
                Pay::create($data);
                OrderTrace::create($trace_data);
                $order_data['mileage'] = $trace_data['distance'];
                $order_data['total_fee'] = $payamount;
                $order_data['driver_amount'] = $driver_amount;
                $order_data['is_end'] = 1;
                $order->save($order_data);
                Db::commit();
            } catch (Exception $e) {
                Db::rollback();
                except($e->getMessage());
            }
        }

        if ($is_third) {
            return compact('paytype', 'apptype', 'response');
        } else {
            if (config('site.is_pay') == 0) {
                $result = self::order_settle($payamount, $order_id, 'order123456', $paytype);
                if (!$result['code']) {
                    except($result['msg']);
                }
                return compact('paytype', 'apptype', 'response');
            }

            $params = [
                'amount' => $payamount,
                'orderid' => $order_id,
                'type' => $paytype,
                'title' => "支付订单，{$payamount}元",
                'method' => $apptype,
            ];
            $response = \app\api\controller\Pay::experience($params, 'order');
            return compact('paytype', 'apptype', 'response');
        }
    }

    /**
     * 订单业务逻辑处理
     *
     * @param float $payamount 支付金额
     * @param float $out_trade_no 订单号
     * @param float $trade_no 交易单号
     * @param float $paytype 支付类型
     * @return mixed
     **/
    public static function order_settle($payamount, $out_trade_no, $trade_no, $paytype)
    {
        $order = Pay::where('order_id', $out_trade_no)
            ->field('id,payamount,status')
            ->find();
        if (!$order) {
            return V(0, '订单不存在');
        }
        if ($payamount != $order['payamount']) {
            return V(0, '订单支付金额不一致');
        }
        if ($order['status'] != CommonConstant::STATUS_CREATED) {
            return V(0, '非待支付状态无法支付');
        }

        Db::startTrans();
        try {
            Order::where('order_id', $out_trade_no)->update(['end_code' => \fast\Random::numeric(4)]);
            $order->payamount = $payamount;
            $order->paytime = date('Y-m-d H:i:s');
            $order->status = CommonConstant::STATUS_PAID;
            $order->transaction_id = $trade_no;
            $order->save();
            Db::commit();
        } catch (Exception $e) {
            Db::rollback();
            return V(0, $e->getMessage());
        }
        return V(1, '支付成功');
    }

    /**
     * 查询订单-扫码支付
     *
     * @param string $order_id 订单号
     * @return mixed
     **/
    public static function order_query($order_id)
    {
        $order = Order::where('order_id', $order_id)->field('status,end_code')->find();
        return $order;
    }

}
